home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume2 / lint-c-front < prev    next >
Encoding:
Internet Message Format  |  1991-08-07  |  8.2 KB

  1. From: rsalz@pineapple.bbn.com
  2. Newsgroups: comp.sources.misc
  3. Subject: v02i045: A C version of the lint driver script
  4. Message-ID: <7193@ncoast.UUCP>
  5. Date: 6 Feb 88 01:24:31 GMT
  6. Approved: allbery@ncoast.UUCP
  7.  
  8. Comp.sources.misc: Volume 2, Issue 45
  9. Submitted-By: "Rich $alz" <rsalz@pineapple.BBN.COM>
  10. Archive-Name: lint-c-front
  11.  
  12. A couple of jobs ago I worked on SysV UniSoft machines, and shell scripts
  13. were painfully slow.  To make sure I knew pipe/fork/exec/wait semantics, I
  14. rewrote the lint script into C code.  The games with exit and _exit helped
  15. shrink program size; a colleague printf/sprinf library that didn't use
  16. standard I/O, so this whole program was under 8K.
  17. As a minimum, some folks might find the transliteration of
  18.     (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1
  19. useful, amusing, or maybe even buggy.  I know it worked back then...
  20.  
  21. Enjoy,
  22.     /r$
  23.  
  24. #! /bin/sh
  25. # This is a shell archive.  Remove anything before this line, then unpack
  26. # it by saving it into a file and typing "sh file".  To overwrite existing
  27. # files, type "sh file -c".  You can also feed this as standard input via
  28. # unshar, or by typing "sh <file", e.g.
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'lint.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'lint.c'\"
  32. else
  33. echo shar: Extracting \"'lint.c'\" \(6486 characters\)
  34. sed "s/^X//" >'lint.c' <<'END_OF_FILE'
  35. X/*
  36. X**  If only for hack value, a C version of the old-fashioned lint script.
  37. X*/
  38. X#include <stdio.h>
  39. X#include <fcntl.h>
  40. X#include <sys/types.h>
  41. X#include <sys/stat.h>
  42. X#include <signal.h>
  43. X
  44. X/* Fundamental constants of the universe. */
  45. X#define ARG_CNT        30
  46. X#define TRUE        1
  47. X#define FALSE        0
  48. X
  49. X/* Argument lists. */
  50. Xchar    *Lint1[ARG_CNT]    = {
  51. X    "/usr/lib/lint/lint1"
  52. X};
  53. Xint     Lint1C        = 1;
  54. X
  55. Xchar    *Lint2[ARG_CNT]    = {
  56. X    "/usr/lib/lint/lint2"
  57. X};
  58. Xint     Lint2C        = 1;
  59. X
  60. Xchar    *Cpp[ARG_CNT]    = {
  61. X    "/lib/cpp",
  62. X    "-DLINT",
  63. X    "-Dlint",
  64. X    "-C"
  65. X};
  66. Xint     CppC        = 4;
  67. X
  68. X/* Other global variables. */
  69. Xchar     Htemp[]    = "/tmp/lintHXXXXXX";
  70. Xchar     Ttemp[]    = "/tmp/lintTXXXXXX";
  71. Xint     Libstat;
  72. Xint     Tfid;
  73. X
  74. X/* Linked in later. */
  75. Xextern int     errno;
  76. Xextern char    *calloc();
  77. Xextern char    *mktemp();
  78. Xextern char    *strcpy();
  79. Xextern char    *strchr();
  80. Xextern char    *strrchr();
  81. X/*+GETOPT ROUTINE
  82. X *
  83. X * A hacked-over version of the one in the standard library.
  84. X */
  85. X
  86. Xint     optind = 1;
  87. Xchar    *optarg;
  88. X
  89. Xint
  90. Xgetopt(ac, av, opts)
  91. X    int              ac;
  92. X    char        **av;
  93. X    char         *opts;
  94. X{
  95. X    static int          sp = 1;
  96. X    register int      c;
  97. X    register char     *cp;
  98. X
  99. X    if (sp == 1)
  100. X    if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
  101. X        return('\0');
  102. X    else if (strcmp(av[optind], "--") == 0)
  103. X    {
  104. X        optind++;
  105. X        return('\0');
  106. X    }
  107. X
  108. X    c = av[optind][sp];
  109. X    if (c == ':' || (cp = strchr(opts, c)) == NULL)
  110. X    yelp("illegal option \"%c\"", c);
  111. X    if (*++cp == ':')
  112. X    {
  113. X    if (av[optind][sp + 1] != '\0')
  114. X        optarg = &av[optind++][sp + 1];
  115. X    else if (++optind >= ac)
  116. X        yelp("option \"%c\" requires an argument", c);
  117. X    else
  118. X        optarg = av[optind++];
  119. X    sp = 1;
  120. X    }
  121. X    else
  122. X    {
  123. X    if (av[optind][++sp] == '\0')
  124. X    {
  125. X        sp = 1;
  126. X        optind++;
  127. X    }
  128. X    optarg = NULL;
  129. X    }
  130. X    return(c);
  131. X}
  132. X/*+SIGNAL CATCHERS AND EXITS
  133. X */
  134. X
  135. X
  136. X#ifdef    LINT
  137. Xextern void     exit();
  138. X#else
  139. Xexit(X)    int X;     { _exit(X); }
  140. X#endif    LINT
  141. X
  142. X
  143. X/* VARARGS1 */
  144. Xyelp(A, B)
  145. X    char    *A;
  146. X    char    *B;
  147. X{
  148. X    int         E;
  149. X
  150. X    E = errno;
  151. X    printf(A, B);
  152. X    printf(" (errno = %d).\n", E);
  153. X    exit(1);
  154. X}
  155. X
  156. X
  157. XRupt()
  158. X{
  159. X    (void)unlink(Htemp);
  160. X    (void)unlink(Ttemp);
  161. X    yelp("\r\nInterrupted!\r\n");
  162. X    /* NOTREACHED */
  163. X}
  164. X/*+UTILITY ROUTINES
  165. X */
  166. X
  167. X
  168. X/*
  169. X * This routine appends a lint library to the T file.
  170. X */
  171. XLib(N, Flag)
  172. X    char        *N;
  173. X    int             Flag;
  174. X{
  175. X    register int     F;
  176. X    register int     i;
  177. X    char         Buff[BUFSIZ];
  178. X
  179. X    if (Flag)
  180. X    sprintf(Buff, "/usr/lib/lint/llib-l%s.ln", N);
  181. X    else
  182. X    (void)strcpy(Buff, N);
  183. X
  184. X    if ((F = open(Buff, O_RDONLY)) < 0)
  185. X    printf("cannot open \"%s\" lint library (errno=%d)", Buff, errno);
  186. X    else
  187. X    {
  188. X    while ((i = read(F, Buff, sizeof Buff)) > 0)
  189. X        (void)write(Tfid, Buff, (unsigned int)i);
  190. X    (void)close(F);
  191. X    }
  192. X}
  193. X
  194. X
  195. X/*
  196. X * This routine concats an argument to an arglist, perhaps preceeding
  197. X * it with a minus sign and a letter.
  198. X */
  199. XAdd(C, Alist, Arg, Simple)
  200. X    int          C;
  201. X    char    **Alist;
  202. X    char     *Arg;
  203. X    char      Simple;
  204. X{
  205. X    int              L;
  206. X    register char     *p;
  207. X
  208. X    if (C >= ARG_CNT - 2)
  209. X    yelp("too many arguments");
  210. X    /* NOTREACHED */
  211. X
  212. X    L = strlen(Arg) + 1;
  213. X    if (Simple)
  214. X    L += 2;
  215. X    p = Alist[C] = calloc((unsigned int)L, 1);
  216. X    if (Simple)
  217. X    {
  218. X    *p++ = '-';
  219. X    *p++ = Simple;
  220. X    }
  221. X    (void)strcpy(p, Arg);
  222. X}
  223. X/*!*/
  224. X/*
  225. X *  This routine is implements this line from the script:
  226. X *    (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1
  227. X */
  228. XDo(N)
  229. X    char    *N;
  230. X{
  231. X    int         P[2];
  232. X
  233. X    if (fork() == 0)
  234. X    {
  235. X    /* The kids run "... 2>&1" */
  236. X    (void)close(2);
  237. X    (void)dup(1);
  238. X    (void)pipe(P);
  239. X
  240. X    Cpp[CppC]    = N;
  241. X    Lint1[Lint1C]    = N;
  242. X
  243. X    if (fork() == 0)
  244. X    {
  245. X        /* Younger child runs "cpp | ..." */
  246. X        (void)close(1);
  247. X        (void)dup(P[1]);
  248. X        (void)close(P[1]);
  249. X        (void)close(P[0]);
  250. X        (void)close(Tfid);
  251. X        (void)execv(Cpp[0], Cpp);
  252. X        yelp("No cpp?");
  253. X        /* NOTREACHED */
  254. X    }
  255. X    else
  256. X    {
  257. X        /* Older child runs "... | lint >> Tfid" */
  258. X        (void)close(0);
  259. X        (void)dup(P[0]);
  260. X        (void)close(P[0]);
  261. X        (void)close(P[1]);
  262. X        (void)close(1);
  263. X        (void)dup(Tfid);
  264. X        (void)close(Tfid);
  265. X        (void)execv(Lint1[0], Lint1);
  266. X        yelp("No lint1?");
  267. X        /* NOTREACHED */
  268. X    }
  269. X    }
  270. X    else
  271. X    (void)wait((int *)0);
  272. X}
  273. X/*+MAIN ROUTINE
  274. X */
  275. X
  276. X
  277. Xmain(ac, av)
  278. X    register int     ac;
  279. X    register char    *av[];
  280. X{
  281. X    register char    *p;
  282. X    register int     c;
  283. X    struct stat         Sb;
  284. X
  285. X    (void)mktemp(Htemp);
  286. X    (void)mktemp(Ttemp);
  287. X    Tfid = open(Ttemp, O_RDWR | O_CREAT | O_APPEND, 0666);
  288. X    Add(Lint2C++, Lint2, Ttemp, 'T');
  289. X
  290. X    /* Parse JCL. */
  291. X    while (c = getopt(ac, av, "abhuvxI:D:U:Nnpl:o:"))
  292. X    switch (c)
  293. X    {
  294. X        /* [abhuvx] -- standard lint flags. */
  295. X        case 'a': case 'b': case 'h': case 'u': case 'v': case 'x':
  296. X        Add(Lint1C++, Lint1, "", c);
  297. X        Add(Lint2C++, Lint2, "", c);
  298. X        break;
  299. X        /* [DIU] -- standard cpp flags. */
  300. X        case 'D': case 'I': case 'U':
  301. X        Add(CppC++, Cpp, optarg, c);
  302. X        break;
  303. X        /* p -- portable library. */
  304. X        case 'p':
  305. X        Add(Lint1C++, Lint1, "", c);
  306. X        Add(Lint2C++, Lint1, "", c);
  307. X        /* [Nn] -- net or no library. */
  308. X        case 'N': case 'n':
  309. X        Libstat = c;
  310. X        break;
  311. X        /* l -- lint library. */
  312. X        case 'l':
  313. X        Lib(optarg, TRUE);
  314. X        break;
  315. X        /* o -- output file (redirection without meta chars). */
  316. X        case 'o':
  317. X        (void)close(1);
  318. X        (void)open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  319. X        break;
  320. X    }
  321. X
  322. X    Add(Lint1C++, Lint1, Htemp, 'H');
  323. X    Add(Lint2C++, Lint2, Htemp, 'H');
  324. X    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  325. X    (void)signal(SIGINT, Rupt);
  326. X
  327. X    /* Did flags; do filenames and libraries. */
  328. X    for (; optind < ac; optind++)
  329. X    {
  330. X    /* Check for -l.. argument. */
  331. X    if (*(p = av[optind]) == '-' && *++p == 'l')
  332. X    {
  333. X        Lib(++p, TRUE);
  334. X        continue;
  335. X    }
  336. X
  337. X    /* Check for *.c for *.ln arguments. */
  338. X    if (p = strrchr(av[optind], '.'))
  339. X    {
  340. X        if (*++p == 'c' && p[1] == '\0')
  341. X        {
  342. X        Do(av[optind]);
  343. X        continue;
  344. X        }
  345. X        if (p[0] == 'l' && p[1] == 'n' && p[2] == '\0')
  346. X        {
  347. X        Lib(av[optind], FALSE);
  348. X        continue;
  349. X        }
  350. X    }
  351. X    printf("Not grokked -- \"%s\" -- ignored\n", av[optind]);
  352. X    }
  353. X
  354. X    /* Any standard C library? */
  355. X    switch (Libstat)
  356. X    {
  357. X    case '\0':    Lib("c", TRUE);        break;
  358. X    case 'N':    Lib("netc", TRUE);
  359. X            Lib("net", TRUE);    break;
  360. X    case 'p':    Lib("port", TRUE);    break;
  361. X    }
  362. X
  363. X    (void)close(Tfid);
  364. X
  365. X    /* If lint1 created anything, run lint2. */
  366. X    if (stat(Htemp, &Sb) >= 0 && Sb.st_size >= 0)
  367. X    {
  368. X    Add(Lint2C, Lint2, Htemp, 'H');
  369. X    if (fork() == 0)
  370. X    {
  371. X        (void)execv(Lint2[0], Lint2);
  372. X        yelp("No lint2?");
  373. X        /* NOTREACHED */
  374. X    }
  375. X    (void)wait((int *)0);
  376. X    }
  377. X
  378. X    /* That's all she wrote. */
  379. X    (void)unlink(Htemp);
  380. X    (void)unlink(Ttemp);
  381. X    exit(0);
  382. X}
  383. END_OF_FILE
  384. if test 6486 -ne `wc -c <'lint.c'`; then
  385.     echo shar: \"'lint.c'\" unpacked with wrong size!
  386. fi
  387. # end of 'lint.c'
  388. fi
  389. echo shar: End of shell archive.
  390. exit 0
  391.